﻿










using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using InSafetyAirServer.Database;
using InSafetyAirServer.Model;
using System.ComponentModel;
using InSafetyAirServer.Controller;
using System.Reflection;
using System.Diagnostics;

namespace InSafetyAirServer
{
    public class Service : IService
    {
        public IList<Path<Airport, Schedule>> searchForFlight(Airport startAirport, Airport endAirport, string criteria, DateTime time, int personsNo, int stops)
        {
            GraphCustom flights = new GraphCustom();
            IList<Airport> airports = Functions.getInstance().GetAll<Airport>();
            foreach (Airport airport in airports)
            {
                flights.AddVertex(new Vertex<Airport, Schedule>(airport));
            }


            flights.AddEdgesToGraph(startAirport, stops, time, personsNo);

            startAirport = Functions.getInstance().GetById<Airport>(startAirport.airportId);
            endAirport = Functions.getInstance().GetById<Airport>(endAirport.airportId);

            Vertex<Airport, Schedule> startVertex = flights.getVertex(startAirport);
            Vertex<Airport, Schedule> endVertex = flights.getVertex(endAirport);
            return flights.YenKSP(startVertex, endVertex, criteria, time, personsNo, stops);
        }

        public Account createAccount(Person person, string username, string password, string email, byte access)
        {
            return AccountCtr.createAccount(person, username, password, email, access);
        }

        public void updatePerson(Person p)
        {
            Functions.getInstance().updatePerson(p);
        }

        public void updateFlight(Flight f)
        {
            Functions.getInstance().updateFlight(f);
        }

        public void updateSchedule(Schedule p)
        {
            Functions.getInstance().updateSchedule(p);
        }

        public void updateSegment(FlightSegment p)
        {
            Functions.getInstance().updateSegemnt(p);
        }

        public Account checkLogin(string username, string password)
        {
            return Functions.getInstance().checkLogin(username, password);
        }

        public OurClass[] GetAll(string type)
        {
            IEnumerator<Type> enumer = Functions.getInstance().GetDatabaseClassesEnumerator();
            bool found = false;
            Type tip = Type.GetType(typeof(SQLDatabaseDataContext).Namespace + "." + type);
            OurClass[] objList = null;
            while (!found && enumer.MoveNext())
            {
                if (tip == enumer.Current)
                {
                    found = true;

                    var doSomething = Functions.getInstance().GetType().GetMethod("GetAll").MakeGenericMethod(tip);
                    objList = (OurClass[])doSomething.Invoke(Functions.getInstance(), new object[] { });
                }
            }
            return objList;
        }

        public OurClass GetById(string type, int id)
        {
            IEnumerator<Type> enumer = Functions.getInstance().GetDatabaseClassesEnumerator();
            bool found = false;
            Type tip = Type.GetType(typeof(SQLDatabaseDataContext).Namespace + "." + type);
            OurClass obj = null;
            while (!found && enumer.MoveNext())
            {
                if (tip == enumer.Current)
                {
                    found = true;

                    var doSomething = Functions.getInstance().GetType().GetMethod("GetById").MakeGenericMethod(tip);
                    obj = (OurClass)doSomething.Invoke(Functions.getInstance(), new object[] { id });
                }
            }
            return obj;
        }

        public OurClass AddToDatabase(OurClass obj)
        {
            IEnumerator<Type> enumer = Functions.getInstance().GetDatabaseClassesEnumerator();
            bool found = false;
            OurClass theObject = null;
            Type tip = obj.GetType();
            while (!found && enumer.MoveNext())
            {
                if (tip == enumer.Current)
                {
                    found = true;
                    var doSomething = Functions.getInstance().GetType().GetMethod("AddToDatabase").MakeGenericMethod(tip);
                    theObject = (OurClass)doSomething.Invoke(Functions.getInstance(), new object[] { obj });
                }
            }
            return theObject;
        }

        public void UpdateToDatabase(OurClass obj)
        {
            IEnumerator<Type> enumer = Functions.getInstance().GetDatabaseClassesEnumerator();
            bool found = false;
            Type tip = obj.GetType();
            while (!found && enumer.MoveNext())
            {
                if (tip == enumer.Current)
                {
                    found = true;

                    var doSomething = Functions.getInstance().GetType().GetMethod("UpdateToDatabase").MakeGenericMethod(tip);
                    doSomething.Invoke(Functions.getInstance(), new object[] { obj });
                }
            }
        }

        public bool makeBooking(int accoundId, List<BookingLine> bookingLines, List<int> schedules, List<Person> persons)
        {

            bool created = false;
            //try
            //{

                Booking booking = new Booking();
                booking.date = DateTime.Now;
                booking.status = 0;
                booking.totalprice = 0;
                booking.accountId = accoundId;
                Functions.getInstance().insOnSubmit<Booking>(booking);

                bool fail = false;
                foreach (BookingLine bl in bookingLines)
                {

                    //create the bookingLine and adding it to database
                    BookingLine bookingLine = new BookingLine();
                    bookingLine.price = bl.price;
                    bookingLine.Booking = booking;
                    Functions.getInstance().insOnSubmit<BookingLine>(bookingLine);

                    //create BL_S - linking together booking lines and schedules

                    foreach (int s in schedules)
                    {
                        Schedule schedule = Functions.getInstance().GetById<Schedule>(s);
                        int freeSeats = Functions.getInstance().findFreeSeats(schedule);
                        if (freeSeats < persons.Count) fail = true;
                        BL_S bl_s = new BL_S();
                        bl_s.BookingLine = bookingLine;
                        bl_s.scheduleId = s;
                        Functions.getInstance().insOnSubmit<BL_S>(bl_s);
                    }

                    foreach (Person pers in persons)
                    {
                        PersonBookingLine persBookLine = new PersonBookingLine();
                        persBookLine.BookingLine = bookingLine;
                        persBookLine.Person = pers;
                        Functions.getInstance().insOnSubmit<PersonBookingLine>(persBookLine);
                    }
                }
                if (!fail)
                {
                    Functions.getInstance().submit();
                    created = true;
                }
                
            //}
            //catch (Exception ex)
            //{
            //    created = false;
            //}

            return created;

        }



        public void DeleteFromDatabase(OurClass obj)
        {
            IEnumerator<Type> enumer = Functions.getInstance().GetDatabaseClassesEnumerator();
            bool found = false;
            Type tip = obj.GetType();
            while (!found && enumer.MoveNext())
            {
                if (tip == enumer.Current)
                {
                    found = true;

                    var doSomething = Functions.getInstance().GetType().GetMethod("DeleteFromDatabase").MakeGenericMethod(tip);
                    doSomething.Invoke(Functions.getInstance(), new object[] { obj });
                }
            }
        }

        public List<FlightSegment> getFlightSegments(int flightid)
        {
            return Functions.getInstance().GetAllByField<FlightSegment>("flightId", flightid).ToList();
        }

        public List<Schedule> getSchedules(int segmentId)
        {
            return Functions.getInstance().GetAllByField<Schedule>("flightSegmentId", segmentId).ToList();
        }

        public int getFreeSeats(int scheduleId)
        {
            return Functions.getInstance().findFreeSeats(Functions.getInstance().GetById<Schedule>(scheduleId));
        }
    }
}
